#pragma once

#include "Hazel/src/Hazel/Render/Shader.h"
#include <glm/glm.hpp>
typedef unsigned int GLenum;
namespace Hazel
{

class OpenGLShader : public Shader
{
  public:
    OpenGLShader(const std::string &name, const std::string &vertexSrc, const std::string &fragmentSrc);
    OpenGLShader(const std::string &filepath);
    virtual ~OpenGLShader();

    virtual void Bind() const override;
    virtual void Unbind() const override;

    virtual void SetInt(const std::string name, int value) override;
    virtual void SetIntArray(const std::string name, int *values, uint32_t count) override;
    virtual void SetFloat(const std::string name, float value) override;
    virtual void SetFloat3(const std::string name, const glm::vec3 &value) override;
    virtual void SetFloat4(const std::string name, const glm::vec4 &value) override;
    virtual void SetMat4(const std::string name, const glm::mat4 &value) override;

    virtual const std::string &GetName() const override
    {
        return m_name;
    }

    void UploadUniformMat3(const std::string &name, const glm::mat3 &matrix);
    void UploadUniformMat4(const std::string &name, const glm::mat4 &matrix);

    void UploadUniformInt(const std::string &name, int value);
    void UploadUniformIntArray(const std::string &name, int *values, uint32_t count);
    void UploadUniformFloat(const std::string &name, float value);
    void UploadUniformFloat2(const std::string &name, const glm::vec2 &values);
    void UploadUniformFloat3(const std::string &name, const glm::vec3 &values);
    void UploadUniformFloat4(const std::string &name, const glm::vec4 &values);
    // void UploadUniformFloat4(const std::string& name,const glm::vec4& values);
  private:
    std::string ReadFile(const std::string &filepath);
    std::unordered_map<GLenum, std::string> PreProcess(const std::string &source);
    void Compile(const std::unordered_map<GLenum, std::string> &shaderSources);

  private:
    uint32_t m_RendererID;
    std::string m_name;
};
} // namespace Hazel